package tau.pimpmyfreedb.GUI;

import java.util.ArrayList;
import java.util.Arrays;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import tau.pimpmyfreedb.common.types.Album;
import tau.pimpmyfreedb.common.types.Artist;
import tau.pimpmyfreedb.common.types.MusicItem;
import tau.pimpmyfreedb.common.types.Track;
import tau.pimpmyfreedb.common.types.TrackLength;
import tau.pimpmyfreedb.dal.DataType;
import tau.pimpmyfreedb.dal.IDataItem;
import tau.pimpmyfreedb.master.IPimpMaster;

public class EditWindow {
    private Shell shell, parent;
    public EditWindowMode mode;
    private AddExistWindow addExistWindow;
    private Label lDescription, lTitle, lArtists;
    private Text tName, tAlbum, tYear, tLengthMin, tLengthSec, tGenere,
	    tDescription;
    private Button bAddArtist, bRemoveArtist, bOk, bCancel;
    private Composite cLeftText, cRightText, cListArtists, cClose;
    private List liArtist;// , liTracks;
    private GridData gridData;
    public String newName, newAlbum, newYear, newLengthMin, newLengthSec,
	    newGenere, newDesc;
    public String[] newArtistList, newTrackList;
    private DataType dataType;
    private java.util.List<MusicItem> newMusicItems, oldMusicItems;
    private IPimpMaster master;
    private MusicItem current;
    private boolean isTopEditWindow;

    VerifyListener numericVerifyListener = new VerifyListener() {

	@Override
	public void verifyText(final VerifyEvent event) {
	    switch (event.keyCode) {
	    case SWT.BS: // Backspace
	    case SWT.DEL: // Delete
	    case SWT.HOME: // Home
	    case SWT.END: // End
	    case SWT.ARROW_LEFT: // Left arrow
	    case SWT.ARROW_RIGHT: // Right arrow
		return;
	    }

	    if (!Character.isDigit(event.character)) {
		event.doit = false; // disallow the action
	    }
	}

    };

    public enum EditWindowMode {
	EDIT, ADD
    };

    public EditWindow(Shell parent, IPimpMaster master, EditWindowMode mode,
	    boolean isTopEditWindow) {
	this.parent = parent;
	this.master = master;
	shell = CreateShell(parent);
	oldMusicItems = new ArrayList<MusicItem>();
	newMusicItems = new ArrayList<MusicItem>();
	this.mode = mode;
	this.addExistWindow = null;
	this.setTopEditWindow(isTopEditWindow);
	CreateLeftTextComposite();
	CreateRightTextComposite();
	CreateDesciption();
	CreateArtistComposite();
	CreateCloseComposite();
    }

    public EditWindow(Shell parent, IPimpMaster master,
	    AddExistWindow callingWindow, boolean isTopEditWindow) {
	this.parent = parent;
	this.master = master;
	shell = CreateShell(parent);
	oldMusicItems = new ArrayList<MusicItem>();
	newMusicItems = new ArrayList<MusicItem>();
	this.mode = EditWindowMode.ADD;
	this.addExistWindow = callingWindow;
	this.setTopEditWindow(isTopEditWindow);

	CreateLeftTextComposite();
	CreateRightTextComposite();
	CreateDesciption();
	CreateArtistComposite();
	// CreateTracksComposite();
	CreateCloseComposite();
    }

    public void run() {
	shell.pack();
	if (parent != null) {
	    // parent.setEnabled(false);
	}
	shell.addDisposeListener(new DisposeListener() {
	    @Override
	    public void widgetDisposed(DisposeEvent e) {
		master.handleCancelEdit(EditWindow.this);
	    }
	});
	shell.open();
	shell.setFocus();
    }

    public void close() {
	if (parent != null) {
	    // parent.setEnabled(true);
	}
	shell.dispose();
    }

    private void saveFields() {
	newName = tName.getText();
	newAlbum = tAlbum.getText();
	newDesc = tDescription.getText();
	newGenere = tGenere.getText();
	newLengthMin = tLengthMin.getText();
	newLengthSec = tLengthSec.getText();
	newYear = tYear.getText();
	newArtistList = liArtist.getItems();
	switch (dataType) {
	case ARTIST:
	    if (current != null) {
		current = new Artist(current.getDataId(), newName, newDesc);
	    } else {
		current = new Artist(IDataItem.NewItemId, newName, newDesc);
	    }

	    break;
	case ALBUM:
	    if (current != null) {
		current = new Album(current.getDataId(), newName, newGenere,
			SWTUtil.String2Int(newYear), newDesc);
	    } else {
		current = new Album(IDataItem.NewItemId, newName, newGenere,
			SWTUtil.String2Int(newYear), newDesc);
	    }
	    break;
	case TRACK:
	    if (current != null) {
		current = new Track(current.getDataId(), newName,
			((Track) current).getAlbumID(), new TrackLength(
				SWTUtil.String2Int(newLengthMin),
				SWTUtil.String2Int(newLengthSec)), newDesc);
	    } else {
		current = new Track(IDataItem.NewItemId, newName,
			Track.UKNOWN_ALBUM_ID, new TrackLength(
				SWTUtil.String2Int(newLengthMin),
				SWTUtil.String2Int(newLengthSec)), newDesc);
	    }
	    break;
	default:
	    break;
	}

	// newTrackList = liTracks.getItems();
    }

    private void CreateCloseComposite() {
	cClose = new Composite(shell, SWT.NONE);
	cClose.setLayout(new GridLayout(3, false));
	gridData = new GridData();
	gridData.horizontalSpan = 2;
	gridData.grabExcessHorizontalSpace = true;
	gridData.horizontalAlignment = SWT.FILL;
	cClose.setLayoutData(gridData);

	bCancel = new Button(cClose, SWT.PUSH);
	bCancel.setText("Cancel");
	gridData = new GridData();
	gridData.horizontalAlignment = SWT.LEFT;
	bCancel.setLayoutData(gridData);
	bCancel.addSelectionListener(new SelectionAdapter() {
	    @Override
	    public void widgetSelected(SelectionEvent e) {
		master.handleCancelEdit(EditWindow.this);
	    }
	});

	Label dummyLabel = new Label(cClose, SWT.NONE);
	gridData = new GridData();
	gridData.grabExcessHorizontalSpace = true;
	gridData.horizontalAlignment = SWT.FILL;
	dummyLabel.setLayoutData(gridData);
	dummyLabel.setText(" ");

	bOk = new Button(cClose, SWT.PUSH);
	bOk.setText("Done");
	gridData = new GridData();
	gridData.horizontalAlignment = SWT.RIGHT;
	bOk.setLayoutData(gridData);
	bOk.addSelectionListener(new SelectionAdapter() {
	    @Override
	    public void widgetSelected(SelectionEvent e) {
		saveFields();
		master.handleEditResults(EditWindow.this);
	    }
	});
    }

    // private void CreateTracksComposite() {
    // cListTracks = new Composite(shell, SWT.BORDER);
    // cListTracks.setLayout(new GridLayout(2, false));
    // gridData = new GridData();
    // gridData.horizontalAlignment = SWT.FILL;
    // gridData.verticalAlignment = SWT.FILL;
    // gridData.grabExcessVerticalSpace = true;
    //
    // cListTracks.setLayoutData(gridData);
    //
    // Label lTracks = new Label(cListTracks, SWT.NONE);
    // lTracks.setText("Tracks");
    // gridData = new GridData();
    // gridData.horizontalAlignment = SWT.CENTER;
    // gridData.horizontalSpan = 2;
    // lTracks.setLayoutData(gridData);
    //
    // liTracks = new List(cListTracks, SWT.V_SCROLL);
    // gridData = new GridData();
    // gridData.verticalAlignment = SWT.FILL;
    // gridData.verticalSpan = 4;
    // gridData.horizontalAlignment = SWT.FILL;
    // gridData.grabExcessHorizontalSpace = true;
    // gridData.grabExcessVerticalSpace = true;
    // liTracks.setLayoutData(gridData);
    //
    // bAddTrack = new Button(cListTracks, SWT.PUSH);
    // bAddTrack.setText("Add");
    // gridData = new GridData();
    // gridData.horizontalAlignment = SWT.FILL;
    // bAddTrack.setLayoutData(gridData);
    //
    // bAddTrack.addSelectionListener(new SelectionAdapter() {
    // @Override
    // public void widgetSelected(SelectionEvent e) {
    // addTrack();
    // }
    // });
    //
    // bRemoveTrack = new Button(cListTracks, SWT.PUSH);
    // bRemoveTrack.setText("Remove");
    // gridData = new GridData();
    // gridData.horizontalAlignment = SWT.FILL;
    // bRemoveTrack.setLayoutData(gridData);
    //
    // bRemoveTrack.addSelectionListener(new SelectionAdapter() {
    // @Override
    // public void widgetSelected(SelectionEvent e) {
    // removeSelection(liTracks);
    // }
    // });
    //
    // new Label(cListTracks, SWT.NONE).setText(" ");
    // new Label(cListTracks, SWT.NONE).setText(" ");
    // }

    private void CreateArtistComposite() {
	cListArtists = new Composite(shell, SWT.BORDER);
	cListArtists.setLayout(new GridLayout(2, false));
	gridData = new GridData();
	gridData.horizontalAlignment = SWT.CENTER;
	gridData.verticalAlignment = SWT.FILL;
	gridData.grabExcessVerticalSpace = true;
	gridData.horizontalSpan = 2;
	cListArtists.setLayoutData(gridData);

	lArtists = new Label(cListArtists, SWT.NONE);
	lArtists.setText("Albums");
	gridData = new GridData();
	gridData.horizontalAlignment = SWT.CENTER;
	gridData.horizontalSpan = 2;
	lArtists.setLayoutData(gridData);

	liArtist = new List(cListArtists, SWT.V_SCROLL);
	gridData = new GridData();
	gridData.verticalAlignment = SWT.FILL;
	gridData.verticalSpan = 4;
	gridData.horizontalAlignment = SWT.FILL;
	gridData.grabExcessHorizontalSpace = true;
	gridData.grabExcessVerticalSpace = true;
	liArtist.setLayoutData(gridData);

	bAddArtist = new Button(cListArtists, SWT.PUSH);
	bAddArtist.setText("Add");
	gridData = new GridData();
	gridData.horizontalAlignment = SWT.FILL;
	bAddArtist.setLayoutData(gridData);

	bAddArtist.addSelectionListener(new SelectionAdapter() {
	    @Override
	    public void widgetSelected(SelectionEvent e) {
		if (EditWindow.this.dataType == DataType.ARTIST) {
		    addAlbum();
		} else if (EditWindow.this.dataType == DataType.ALBUM) {
		    addTrack();
		}
	    }
	});

	bRemoveArtist = new Button(cListArtists, SWT.PUSH);
	bRemoveArtist.setText("Remove");
	gridData = new GridData();
	gridData.horizontalAlignment = SWT.FILL;
	bRemoveArtist.setLayoutData(gridData);

	bRemoveArtist.addSelectionListener(new SelectionAdapter() {
	    @Override
	    public void widgetSelected(SelectionEvent e) {
		removeSelection(liArtist);
	    }
	});

	new Label(cListArtists, SWT.NONE).setText(" ");
	new Label(cListArtists, SWT.NONE).setText(" ");
    }

    private void CreateDesciption() {
	lDescription = new Label(shell, SWT.NONE);
	lDescription.setText("Description:");
	gridData = new GridData();
	gridData.horizontalSpan = 2;
	lDescription.setLayoutData(gridData);

	tDescription = new Text(shell, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
	gridData = new GridData(GridData.FILL_BOTH);
	gridData.horizontalSpan = 2;
	gridData.heightHint = 100;
	tDescription.setLayoutData(gridData);
    }

    private void CreateRightTextComposite() {
	cRightText = new Composite(shell, SWT.BORDER);
	cRightText.setLayout(new GridLayout(2, false));
	gridData = new GridData();
	gridData.grabExcessHorizontalSpace = true;
	gridData.horizontalAlignment = SWT.FILL;
	cRightText.setLayoutData(gridData);

	new Label(cRightText, SWT.NONE).setText("Album:");
	tAlbum = new Text(cRightText, SWT.NONE);
	gridData = new GridData();
	gridData.horizontalAlignment = SWT.FILL;
	tAlbum.setLayoutData(gridData);

	new Label(cRightText, SWT.NONE).setText("Length(Minutes):");
	tLengthMin = new Text(cRightText, SWT.NONE);
	gridData = new GridData();
	gridData.horizontalAlignment = SWT.FILL;
	tLengthMin.setLayoutData(gridData);
	tLengthMin.addVerifyListener(numericVerifyListener);

	new Label(cRightText, SWT.NONE).setText("Length(Seconds):");
	tLengthSec = new Text(cRightText, SWT.NONE);
	gridData = new GridData();
	gridData.horizontalAlignment = SWT.FILL;
	tLengthSec.setLayoutData(gridData);
	tLengthSec.addVerifyListener(numericVerifyListener);
    }

    private void CreateLeftTextComposite() {
	cLeftText = new Composite(shell, SWT.BORDER);
	cLeftText.setLayout(new GridLayout(2, false));
	gridData = new GridData();
	gridData.grabExcessHorizontalSpace = true;
	gridData.horizontalAlignment = SWT.FILL;
	cLeftText.setLayoutData(gridData);

	new Label(cLeftText, SWT.NONE).setText("Name:");
	tName = new Text(cLeftText, SWT.NONE);
	gridData = new GridData();
	gridData.horizontalAlignment = SWT.FILL;
	tName.setLayoutData(gridData);

	new Label(cLeftText, SWT.NONE).setText("Genere:");
	tGenere = new Text(cLeftText, SWT.NONE);
	gridData = new GridData();
	gridData.horizontalAlignment = SWT.FILL;
	tGenere.setLayoutData(gridData);

	new Label(cLeftText, SWT.NONE).setText("Year:");
	tYear = new Text(cLeftText, SWT.NONE);
	gridData = new GridData();
	gridData.horizontalAlignment = SWT.FILL;
	tYear.setLayoutData(gridData);
	tYear.addVerifyListener(numericVerifyListener);
    }

    private Shell CreateShell(Shell parent) {
	shell = SWTUtil.getShell(parent);
	shell.setLayout(new GridLayout(2, true));

	lTitle = new Label(shell, SWT.NONE);
	lTitle.setText("Edit Window");
	GridData gridData = new GridData();
	gridData.horizontalSpan = 2;
	gridData.horizontalAlignment = SWT.CENTER;
	lTitle.setLayoutData(gridData);

	FontData[] fontData = lTitle.getFont().getFontData();
	fontData[0].setHeight(16);
	fontData[0].setStyle(SWT.BOLD);
	final Font nameLabelFont = new Font(shell.getDisplay(), fontData);
	lTitle.setFont(nameLabelFont);
	// add dispose listener (Font must be disposed)
	lTitle.addDisposeListener(new DisposeListener() {
	    @Override
	    public void widgetDisposed(DisposeEvent e) {
		nameLabelFont.dispose();

	    }
	});
	return shell;

    }

    public void setAlbumMode(MusicItem curr, String year, String name,
	    MusicItem[] tracks, String genere, String desc) {
	if (!shell.isDisposed()) {
	    current = curr;
	    dataType = DataType.ALBUM;
	    cRightText.setEnabled(false);
	    cRightText.setVisible(false);

	    lTitle.setText(name + " (" + SWTUtil.dataType2String(dataType)
		    + ")");
	    lArtists.setText("Tracks");
	    tDescription.setText(desc);
	    if (genere == null) {
		genere = "";
	    }
	    tGenere.setText(genere);
	    tName.setText(name);
	    tYear.removeVerifyListener(numericVerifyListener);
	    tYear.setText(year);
	    tYear.addVerifyListener(numericVerifyListener);
	    if (tracks != null) {
		SWTUtil.PopulateList(tracks, liArtist);
		oldMusicItems = new ArrayList<MusicItem>(Arrays.asList(tracks));
		newMusicItems = new ArrayList<MusicItem>(Arrays.asList(tracks));
		// newMusicItems = oldMusicItems;

	    } else {
		oldMusicItems = new ArrayList<MusicItem>();
		newMusicItems = new ArrayList<MusicItem>();
	    }
	    shell.pack();
	}
    }

    public void setArtistMode(MusicItem curr, String name, String desc,
	    MusicItem[] albums) {
	if (!shell.isDisposed()) {
	    current = curr;
	    dataType = DataType.ARTIST;
	    cRightText.setEnabled(false);
	    cRightText.setVisible(false);
	    tYear.setEnabled(false);
	    tYear.setVisible(false);
	    // cListArtists.setEnabled(false);
	    // cListTracks.setEnabled(false);
	    tGenere.setEnabled(false);
	    tGenere.setVisible(false);

	    if (albums != null) {
		SWTUtil.PopulateList(albums, liArtist);
		oldMusicItems = new ArrayList<MusicItem>(Arrays.asList(albums));
		newMusicItems = new ArrayList<MusicItem>(Arrays.asList(albums));
		// newMusicItems = oldMusicItems;
	    }
	    lArtists.setText("Albums");
	    tDescription.setText(desc);
	    tName.setText(name);
	    lTitle.setText(name + " (" + SWTUtil.dataType2String(dataType)
		    + ")");
	    shell.pack();
	}
    }

    public void setTrackMode(MusicItem curr, String name, String album,
	    String minLen, String secLen, String desc) {
	if (!shell.isDisposed()) {
	    current = curr;
	    dataType = DataType.TRACK;

	    tYear.setEnabled(false);
	    tYear.setVisible(false);

	    cListArtists.setEnabled(false);
	    cListArtists.setVisible(false);
	    // cListTracks.setEnabled(false);
	    tAlbum.setEnabled(false);
	    tAlbum.setVisible(false);

	    tGenere.setEnabled(false);
	    tGenere.setVisible(false);

	    lArtists.setText("");
	    tDescription.setText(desc);
	    tName.setText(name);
	    tAlbum.setText(album);
	    lTitle.setText(name + " (" + SWTUtil.dataType2String(dataType)
		    + ")");
	    tLengthMin.removeVerifyListener(numericVerifyListener);
	    tLengthSec.removeVerifyListener(numericVerifyListener);
	    tLengthMin.setText(minLen);
	    tLengthSec.setText(secLen);
	    tLengthMin.addVerifyListener(numericVerifyListener);
	    tLengthSec.addVerifyListener(numericVerifyListener);
	    shell.pack();
	}
    }

    private void addTrack() {
	master.addDataType(this, DataType.TRACK);
	// String name = openInputBox("Please enter the track's Name");
	// if (name != null)
	// liTracks.add(name);

    }

    private void addAlbum() {
	master.addDataType(this, DataType.ALBUM);
    }

    private void removeSelection(List list) {
	if (list.getSelectionIndex() != -1) {
	    MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION
		    | SWT.CANCEL | SWT.OK);
	    mb.setMessage("Are you sure?");
	    if (dataType == DataType.ALBUM) {
		mb.setMessage("Are you Sure?\nThe the track will be deleted from the system permenatly.");
	    }
	    int buttonID = mb.open();
	    if (buttonID == SWT.OK) {
		master.removeItem(this);
	    }
	}
    }

    public MusicItem getCurrentMusicItem() {
	return current;
    }

    public void addMusicItem(MusicItem mi) {
	if (mi != null) {
	    newMusicItems.add(mi);
	    liArtist.add(mi.getName());
	}
    }

    public java.util.List<MusicItem> getRelationsList() {
	return newMusicItems;
    }

    public java.util.List<MusicItem> getOldRelationsList() {
	return oldMusicItems;
    }

    public EditWindowMode getMode() {
	return mode;
    }

    public DataType getDataType() {
	return dataType;
    }

    public Shell getShell() {
	return shell;
    }

    public MusicItem getSelectedMusicItem() {
	int index = liArtist.getSelectionIndex();
	return newMusicItems.get(index);
    }

    public void removeMusicItem(MusicItem musicItem) {
	liArtist.remove(musicItem.getName());
	newMusicItems.remove(musicItem);
    }

    public AddExistWindow getAddExistWindow() {
	return addExistWindow;
    }

    public boolean isTopEditWindow() {
	return isTopEditWindow;
    }

    public void setTopEditWindow(boolean isTopEditWindow) {
	this.isTopEditWindow = isTopEditWindow;
    }
}
